function trStopCache() {
	
	// ensure this is called as constructor
	
	if (!(this instanceof trStopCache)) {
		return new trStopCache();
	}
	
	// make this a singleton
	
	if (typeof trStopCache.instance === "object") {
		return trStopCache.instance;
	}
	
	trStopCache.instance = this;
	
	this.cache = {}; // our cache element
	
	this.addToCache = function(agency,stop_id,data) {
		if (this.cache[agency] == undefined) {
			this.cache[agency] = {};
		}
		this.cache[agency][stop_id] = data;
	}
	
  	
	this.checkCached = function(arrivals_object,stop_config,callback) {
		// initialize recursive retrieval of cache items
		var next_stop = this.nextUncachedStop(stop_config);
		this.getCacheItem(arrivals_object,stop_config,next_stop,callback);
    
	}
	
	this.getCacheItem = function(arrivals_object,stop_config,stop,callback) {
		
		this.cache[stop.agency][stop.stop_id] = false;
		// get the stop info
		var service_url = "http://transitappliance.couchone.com/transit_stops_production/"+stop.agency+":"+stop.stop_id;

		jQuery('#arrivals_log_area').append("Loading info for "+stop.agency+" stop "+stop.stop_id+"<br>");
		jQuery.when(jQuery.ajax({
	    type: "GET",
			url: service_url,
			timeout: 2000,
			dataType: "jsonp",
			success: function(data) {
				trStopCache.instance.addToCache(data.agency,data.stop_id,data);
				jQuery('#arrivals_log_area').append("success<br>");
			},
			error: function(){
				jQuery('#arrivals_log_area').append("<font color='red'>error</font><br>");
			}				
		})).done(function(data) {
			next_stop = trStopCache().nextUncachedStop(stop_config);
			if (next_stop.agency == undefined) {
				// ran out of stops
				jQuery('#arrivals_log_area').append("Stop cache built.<br><br>");
				callback(arrivals_object);
			} else {
				// recursively get the next item
				trStopCache().getCacheItem(arrivals_object,stop_config,next_stop,callback);
			}
		}).fail(function(data) {
			next_stop = trStopCache().nextUncachedStop(stop_config);
			if (next_stop.agency == undefined) {
				// ran out of stops
				jQuery('#arrivals_log_area').append("Stop cache built.<br><br>");
				callback(arrivals_object);
			} else {
				// recursively get the next item
				trStopCache().getCacheItem(arrivals_object,stop_config,next_stop,callback);
			}
		});
	}

	
	this.nextUncachedStop = function(stop_config) {
		for (var agency in stop_config) {
			if (this.cache[agency] == undefined) {
				this.cache[agency] = {};
			}
			for (var stop_id in stop_config[agency]) {
				if (this.cache[agency][stop_id] == undefined) {
					return {agency: agency, stop_id: stop_id};
				}
			}
		}
		return {}; // cache must be complete, no apparent uncached items
	}	
	
	this.stopData = function(agency,stop_id) {
		if (this.cache[agency]) {
			if (this.cache[agency][stop_id]) {
				return this.cache[agency][stop_id];
			} else {
				return undefined;
			}
		} else {
			return undefined;
		}
	}
	

}


